//
//  EYClass.m
//  metadata
//
//  Created by easy on 11-5-27.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "EYClass.h"


@implementation EYClass
@synthesize ownClass = own;
@synthesize superClass;
@synthesize version;
@synthesize weakInstanceVariableLayout;
@synthesize instanceSize;
@synthesize instanceVariableLayout;
@synthesize name;
+(id) init:(Class) clazz{
	return [[[EYClass alloc] initWith:clazz] autorelease];
}
-(id) initWith :(Class) clazz{
	if (self = [super init]) {
		own = clazz;
	}
	return self;
}
-(id) createInstance:(size_t) extraBytes{
	return class_createInstance(self.ownClass, extraBytes);
}
-(BOOL) isMetaClass{
	return class_isMetaClass(self.ownClass);
}
#pragma mark property
-(EYProperty *) propertyWithName:(NSString *) aName{
	objc_property_t prop = class_getProperty(self.ownClass, [aName cStringUsingEncoding:DEFAULT_ENCODING]);
	return [EYProperty init:prop];
}
-(NSArray /*EYProperty*/*) propertyList{
	unsigned int outCount = 0;
	objc_property_t *props = class_copyPropertyList(self.ownClass, &outCount);
	NSMutableArray *arr = [NSMutableArray arrayWithCapacity:outCount];
	if (outCount > 0) {
		for (int i = 0; i < outCount; i++) {
			EYProperty *prop = [EYProperty init:*(props+i)];
			[arr addObject:prop];
		}
	} 
	props = nil;
	return arr;
}
-(EYInstanceVariable *) instanceVariableWithName:(NSString *) aName{
	Ivar var = class_getInstanceVariable(self.ownClass, [aName cStringUsingEncoding:DEFAULT_ENCODING]);
	EYInstanceVariable *ivar = [EYInstanceVariable init:var];
	var = nil;
	return ivar;
}
-(EYInstanceVariable *) classVariableWithName:(NSString *) aName{
	Ivar var = class_getClassVariable(self.ownClass, [aName cStringUsingEncoding:DEFAULT_ENCODING]);
	EYInstanceVariable *ivar = [EYInstanceVariable init:var];
	var = nil;
	return ivar;
}
-(NSArray /*EYInstanceVariable*/ *) instanceVariableList{
	unsigned int outCount; 
	Ivar *vars = class_copyIvarList(self.ownClass, &outCount);
	NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:outCount];
	if (outCount > 0) {
		for (int i = 0; i < outCount; i++) {
			EYInstanceVariable *ivar = [[EYInstanceVariable alloc] initWith:*(vars+i)];
			[arr addObject:ivar];
			[ivar release];
		}
	}
	vars = nil;
	return arr;
}
-(BOOL) addInstanceVariable:(NSString *) aName size:(size_t) size alignment:(uint8_t) alignment types:(NSString *) types{
	const char *_name = [aName cStringUsingEncoding:DEFAULT_ENCODING];
	const char *_types = [types cStringUsingEncoding:DEFAULT_ENCODING];
	return class_addIvar(self.ownClass, _name, size, alignment, _types);
}
-(EYMethod *) classMethodWith:(SEL) selector{
	return [EYMethod init:class_getClassMethod(self.ownClass, selector)];
}
-(EYMethod *) instanceMethodWith:(SEL) selector{
	return [EYMethod init:class_getInstanceMethod(self.ownClass, selector)];
}
-(BOOL) addMethod:(SEL) selector imp:(IMP) imp types:(NSString *)types{
	return class_addMethod(self.ownClass, selector, imp, [types cStringUsingEncoding:DEFAULT_ENCODING]);
}
-(NSArray /*EYMethod*/*) methodList{
	unsigned int outCount = 0;
	Method *ms = class_copyMethodList(self.ownClass, &outCount);
	NSMutableArray *arr = [NSMutableArray arrayWithCapacity:outCount];
	if (outCount > 0) {
		for (int i = 0;i < outCount; i++) { 
			EYMethod *m = [[EYMethod alloc] initWith:*(ms + i)];
			[arr addObject:m];
			[m release];
		}
	}
	ms = nil;
	return arr;
}
-(IMP) methodImplementationWith:(SEL) selector{
	return class_getMethodImplementation(self.ownClass, selector);
}
-(IMP) methodImplementationStretWith:(SEL)selector{
	return class_getMethodImplementation_stret(self.ownClass, selector);
}
-(IMP) replaceMethod:(SEL)selector imp:(IMP) imp types:(NSString *) types{
	return class_replaceMethod(self.ownClass, selector, imp, types);
}
-(BOOL) respondsToSelector:(EYSelector *)aSelector{
	return class_respondsToSelector(self.ownClass, aSelector.ownSelector);
}
-(BOOL) addProtocol:(EYProtocol *) protocol{
	return class_addProtocol(self.ownClass, protocol.ownProtocol);
}
-(BOOL) conformsToProtocol:(EYProtocol *)protocol{
	return class_conformsToProtocol(self.ownClass, protocol.ownProtocol);
}
-(NSArray /*EYProtocol*/ *) protocolList{
	unsigned int outCount = 0;
	Protocol ** ps = class_copyProtocolList(self.ownClass, &outCount);
	NSMutableArray *arr = [NSMutableArray arrayWithCapacity:outCount];
	if (outCount > 0) {
		for (int i = 0;i < outCount; i++) {
			EYProtocol *p = [[EYProtocol alloc] initWith:*(ps+i)];
			[arr addObject:p];
			[p release];
		}
	}
	ps = nil;
	return arr;
}
#pragma mark -
#pragma mark setter/getter
 

-(void) dealloc{
	own = nil;
	[super dealloc];
}
-(NSString *) weakInstanceVariableLayout{
	return [NSString stringWithCString:class_getWeakIvarLayout(self.ownClass) encoding:DEFAULT_ENCODING];
}
-(void) setWeakInstanceVariableLayout:(NSString *) layout{
	class_setWeakIvarLayout(self.ownClass, [layout cStringUsingEncoding:DEFAULT_ENCODING]);
}

-(size_t) instanceSize{
	return class_getInstanceSize(self.ownClass);
}
-(NSString *) instanceVariableLayout{
	return [NSString stringWithCString:class_getIvarLayout(self.ownClass) encoding:DEFAULT_ENCODING];
}
-(void) setInstanceVariableLayout:(NSString *) layout{
	class_setIvarLayout(self.ownClass, [layout cStringUsingEncoding:DEFAULT_ENCODING]);
}
-(NSString *) name{
	return [NSString stringWithCString:class_getName(self.ownClass) encoding:DEFAULT_ENCODING];
}
-(void) setSuperClass:(EYClass *) clazz{
	class_setSuperclass(self.ownClass, clazz.ownClass);
}
-(EYClass *) superClass{
	return [EYClass init:class_getSuperclass(self.ownClass)];
}
-(void) setVersion:(int) ver{
	class_setVersion(self.ownClass, ver);
}
-(int) version{
	return class_getVersion(self.ownClass);
}
@end
